/*=============================================================================
PostEffects.cpp : Post processing effects implementation
Copyright (c) 2001 Crytek Studios. All Rights Reserved.

Revision history:
* Created by Tiago Sousa

=============================================================================*/

#include "StdAfx.h"
#include "I3DEngine.h"
#include "PostEffects.h"
#include "PostProcessUtils.h"

std::vector< Vec2 > CWaterRipples::s_pWaterHits[RT_COMMAND_BUF_COUNT];
std::vector< Vec2 > CWaterRipples::s_pWaterHitsMGPU;
Vec3 CWaterRipples::s_CameraPos;
int CWaterRipples::s_nUpdateMask;
Vec4 CWaterRipples::s_vParams;
bool CWaterRipples::s_bInitializeSim;

////////////////////////////////////////////////////////////////////////////////////////////////////
// Engine specific post-effects
////////////////////////////////////////////////////////////////////////////////////////////////////

int CMotionBlur::Initialize()
{
	return 1;
}

int CMotionBlur::CreateResources()
{
	SAFE_RELEASE(m_pBokehShape);
	m_pBokehShape = CTexture::ForName("EngineAssets/ScreenSpace/bokeh_pentagon.dds",  FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);

	return 1;
}

void CMotionBlur::Release()
{ 	
	m_pOMBData[0].clear();
	m_pOMBData[1].clear();
	m_pOMBData[2].clear();

	SAFE_RELEASE( m_pBokehQuadMesh );
	SAFE_RELEASE(m_pBokehShape);
}

void CMotionBlur::Reset(bool bOnSpecChange)
{  
  m_pActive->ResetParam(0.0f);
  
  m_pType->ResetParam(0.0f);  
  m_pQuality->ResetParam(2.0f);  

  m_pAmount->ResetParam(0.5f);

  m_pCameraSphereScale->ResetParam(2.0f);
  m_pExposureTime->ResetParam(0.004f);
  m_pVectorsScale->ResetParam(1.5f);  
  m_pChromaShift->ResetParam(0.0f);
  m_pFocusRange->ResetParam( 1.0f );
  m_pRadialBlurMaskUVScaleX->ResetParam(1.0f);
  m_pRadialBlurMaskUVScaleY->ResetParam(1.0f);

  m_pDrawNearZRangeOverride->ResetParam(0.0f);

  m_bResetPrevScreen = 1;

  m_nSamplesInfo = 0;
  m_fRotSamplesEst = 0.0f;
  m_fTransSamplesEst = 0.0f;
	
	m_pRadialBlurMaskTex->Release(); 

	SAFE_RELEASE( m_pBokehQuadMesh );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

int CDepthOfField::CreateResources()
{
  SAFE_RELEASE( m_pNoise );

  m_pNoise = CTexture::ForName("EngineAssets/Textures/vector_noise.dds",  FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);

	return true;
}

void CDepthOfField::Release()
{
  SAFE_RELEASE( m_pNoise );
}

void CDepthOfField::Reset(bool bOnSpecChange)
{
  m_pUseMask->ResetParam(0.0f);	
  m_pFocusDistance->ResetParam(3.5f);
  m_pFocusRange->ResetParam(0.0f);
  m_pMaxCoC->ResetParam(12.0f);
	m_pCenterWeight->ResetParam(1.0f);
  m_pBlurAmount->ResetParam(1.0f);  
  m_pFocusMin->ResetParam(2.0f);
  m_pFocusMax->ResetParam(10.0f);
  m_pFocusLimit->ResetParam(100.0f);
  m_pUseMask->ResetParam(0.0f);
  m_pMaskTex->Release();    
	
	
	m_pMaskedBlurAmount->ResetParam(0.0f);
	m_pMaskedBlurMaskTex->Release();

	m_pBokehMaskTex->Release();
  m_pDebug->ResetParam(0.0f);
  m_pActive->ResetParam(0.0f);
  
  m_pUserActive->ResetParam(0.0f);
  m_pUserFocusDistance->ResetParam(3.5f);
  m_pUserFocusRange->ResetParam(5.0f);
  m_pUserBlurAmount->ResetParam(1.0f);

	m_pFocusMinZ->ResetParam(0.0f);
	m_pFocusMinZScale->ResetParam(0.0f);

  m_fUserFocusRangeCurr = 0;
  m_fUserFocusDistanceCurr = 0;
  m_fUserBlurAmountCurr = 0;
}

bool CDepthOfField::Preprocess()
{
	if( !CRenderer::CV_r_usezpass || !CRenderer::CV_r_dof || CRenderer::CV_r_UseMergedPosts )  
    return false;

#if !defined(XENON) && !defined(PS3)
	if( CRenderer::CV_r_dof == 2 && gRenDev->IsHDRModeEnabled() ) 
		return false;
#endif

  if((m_pBlurAmount->GetParam() <= 0.1f && m_pUserBlurAmount->GetParam() <= 0.1f) )      
    return false;

  if( IsActive() || m_pUserActive->GetParam() )
    return true;
  
  return false;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

bool CGlow::Preprocess()
{
  // allowed on all specs
  return ( CRenderer::CV_r_glow && IsActive() && m_pScale->GetParam() >0.1f && !gRenDev->IsHDRModeEnabled());
}

void CGlow::Reset(bool bOnSpecChange)
{
  m_pActive->ResetParam(0.0f);
  //m_pScale->ResetParam(0.5f);//0.35f
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

int CSunShafts::Initialize()
{
  Release();

  m_pOcclQuery = new COcclusionQuery;
  m_pOcclQuery->Create();

  return true;
}

void CSunShafts::Release()
{
  SAFE_DELETE( m_pOcclQuery );
}

void CSunShafts::Reset(bool bOnSpecChange)
{
}

void CSunShafts::OnLostDevice()
{
  Release();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

bool CFilterSharpening::Preprocess()
{  
  bool bQualityCheck = CPostEffectsMgr::CheckPostProcessQuality( eRQ_Medium, eSQ_Medium );

  if( !bQualityCheck )
    return false;

  if( !CRenderer::CV_r_PostProcessFilters)
    return false;

  if( fabs(m_pAmount->GetParam() - 1.0f ) > 0.09f )
  {
    return true;
  }

  return false;
}

void CFilterSharpening::Reset(bool bOnSpecChange)
{
  m_pAmount->ResetParam(1.0f);
  m_pType->ResetParam(0.0f);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

bool CFilterBlurring::Preprocess()
{
  bool bQualityCheck = CPostEffectsMgr::CheckPostProcessQuality( eRQ_Medium, eSQ_Medium );

  if( !bQualityCheck )
    return false;

  if( !CRenderer::CV_r_PostProcessFilters)
    return false;

  if( m_pAmount->GetParam() > 0.09f )
  {
    return true;
  }

  return false;
}

void CFilterBlurring::Reset(bool bOnSpecChange)
{
  m_pAmount->ResetParam(0.0f);
  m_pType->ResetParam(0.0f);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

bool CUberGamePostProcess::Preprocess()
{	
	const float fParamThreshold = 1.0f / 255.0f;
	const Vec4 vWhite = Vec4(1.0f, 1.0f, 1.0f, 1.0f);

	bool bEnable = false;	
	bEnable |= m_pColorTint->GetParamVec4() != vWhite;
	bEnable |= m_pNoise->GetParam() > fParamThreshold;	
	bEnable |= m_pSyncWaveAmplitude->GetParam() > fParamThreshold;
	bEnable |= m_pGrainAmount->GetParam() > fParamThreshold;
	bEnable |= m_pPixelationScale->GetParam() > fParamThreshold;
	
	if( m_pInterlationAmount->GetParam() > fParamThreshold || m_pVSyncAmount->GetParam() > fParamThreshold	)
	{
		m_nCurrPostEffectsMask |= ePE_SyncArtifacts;
		bEnable = true;
	}

	const float fParamThresholdBackCompatibility = 0.01f;

	if( m_pChromaShiftAmount->GetParam() > fParamThresholdBackCompatibility || m_pFilterChromaShiftAmount->GetParam() > fParamThresholdBackCompatibility)
	{
		m_nCurrPostEffectsMask |= ePE_ChromaShift;
		bEnable = true;
	}

	return bEnable;
}

void CUberGamePostProcess::Reset(bool bOnSpecChange)
{
	m_nCurrPostEffectsMask = 0;

	m_pVSyncAmount->ResetParam(0.0f);
	m_pVSyncFreq->ResetParam(1.0f);
	
	const Vec4 vWhite = Vec4(1.0f, 1.0f, 1.0f, 1.0f);
	m_pColorTint->ResetParamVec4(vWhite);

	m_pInterlationAmount->ResetParam(0.0f);
	m_pInterlationTilling->ResetParam(1.0f);
	m_pInterlationRotation->ResetParam(0.0f);

	m_pPixelationScale->ResetParam(0.0f);
	m_pNoise->ResetParam(0.0f);
	
	m_pSyncWaveFreq->ResetParam(0.0f);
	m_pSyncWavePhase->ResetParam(0.0f);
	m_pSyncWaveAmplitude->ResetParam(0.0f);

	m_pFilterChromaShiftAmount->ResetParam(0.0f);
	m_pChromaShiftAmount->ResetParam(0.0f);

	m_pGrainAmount->ResetParam(0.0f);
	m_pGrainTile->ResetParam(1.0f);

	m_pMask->Release();    
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

bool CColorGrading::Preprocess()
{
	// Depreceated: to be removed / replaced by UberPostProcess shader
	return false;
}

void CColorGrading::Reset(bool bOnSpecChange)
{
  // reset user params
  m_pSaturationOffset->ResetParam(0.0f);
  m_pPhotoFilterColorOffset->ResetParamVec4( Vec4(0.0f, 0.0f, 0.0f, 0.0f) );
  m_pPhotoFilterColorDensityOffset->ResetParam(0.0f);
  m_pGrainAmountOffset->ResetParam(0.0f);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

bool CUnderwaterGodRays::Preprocess()
{
  bool bQualityCheck = CPostEffectsMgr::CheckPostProcessQuality( eRQ_Medium, eSQ_Medium );
  if( !bQualityCheck )
    return false;

  static ICVar *pVar = iConsole->GetCVar("e_WaterOcean");
  bool bOceanEnabled = (pVar && pVar->GetIVal() != 0);

# ifndef _RELEASE
  if (SRendItem::m_RecurseLevel[gRenDev->m_RP.m_nProcessThreadID]==0) __debugbreak();
# endif
  int nR = SRendItem::m_RecurseLevel[gRenDev->m_RP.m_nProcessThreadID] - 1;
  //bool bOceanVolumeVisible = (gEnv->p3DEngine->GetOceanRenderFlags() & OCR_OCEANVOLUME_VISIBLE) != 0;

  if( CRenderer::CV_r_water_godrays && m_pAmount->GetParam() > 0.005f) // && bOceanEnabled && bOceanVolumeVisible)
  {
    float fWatLevel = SPostEffectsUtils::m_fWaterLevel;
    if( fWatLevel - 0.1f > gRenDev->GetRCamera().Orig.z)
    {
      // check water level

      return true;
    }    
  }
  
  return false;
}

void CUnderwaterGodRays::Reset(bool bOnSpecChange)
{
  m_pAmount->ResetParam(1.0f);
  m_pQuality->ResetParam(1.0f);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

bool CVolumetricScattering::Preprocess()
{
  bool bQualityCheck = CPostEffectsMgr::CheckPostProcessQuality( eRQ_High, eSQ_High );
  if( !bQualityCheck )
    return false;

  if( !CRenderer::CV_r_PostProcessGameFx)
    return false;

  if( m_pAmount->GetParam() > 0.005f)
  {
    return true;
  }

  return false;
}

void CVolumetricScattering::Reset(bool bOnSpecChange)
{
  m_pAmount->ResetParam(0.0f);
  m_pType->ResetParam(0.0f);
  m_pQuality->ResetParam(1.0f);
  m_pTilling->ResetParam(1.0f);
  m_pSpeed->ResetParam(1.0f);
  m_pColor->ResetParamVec4(Vec4( 0.5f, 0.75f, 1.0f, 1.0f ));
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Game/Hud specific post-effects
////////////////////////////////////////////////////////////////////////////////////////////////////

void CAlienInterference::Reset(bool bOnSpecChange)
{
  m_pAmount->ResetParam(0.0f);
	m_pTintColor->ResetParamVec4(Vec4(Vec3(0.85f, 0.95f, 1.25f)*0.5f, 1.0f));
}

bool CAlienInterference::Preprocess()
{
  bool bQualityCheck = CPostEffectsMgr::CheckPostProcessQuality( eRQ_Medium, eSQ_Medium );
  if( !bQualityCheck )
    return false;

  if( !CRenderer::CV_r_PostProcessGameFx)
    return false;

  if( m_pAmount->GetParam() > 0.09f)
  {
    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

bool CWaterDroplets::Preprocess()
{
  bool bQualityCheck = CPostEffectsMgr::CheckPostProcessQuality( eRQ_Medium, eSQ_Medium );
  if( !bQualityCheck )
    return false;

  bool bUserActive = m_pAmount->GetParam() > 0.005f;

  if(gEnv->IsEditing() && !bUserActive)
    return false;

  if( CRenderer::CV_r_water_godrays)
  {
    float fWatLevel = SPostEffectsUtils::m_fWaterLevel;
    if( fWatLevel - 0.1f > gRenDev->GetRCamera().Orig.z)
    {
      m_fLastSpawnTime = 0.0f;
      m_fCurrLifeTime = 0.0;
      m_bWasUnderWater = true;
      return false; 
    }
    else 
      m_bWasUnderWater = false;

    // Coming out of water
    if( m_bWasUnderWater == false && m_fCurrLifeTime <1.0f)
    {
      const float fLifeTime = 1.5f;

      if( !m_fLastSpawnTime )
        m_fLastSpawnTime = gEnv->pTimer->GetCurrTime();

      m_fCurrLifeTime = (gEnv->pTimer->GetCurrTime() - m_fLastSpawnTime) / fLifeTime;
      if( m_fCurrLifeTime >= 1.0f)
      {
        if( !bUserActive ) // user enabled override
          return false;
      }

      // check water level
      return true;
    }

    if( bUserActive ) // user enabled override
      return true;
  }

  return false;
}

void CWaterDroplets::Reset(bool bOnSpecChange)
{  
  m_fLastSpawnTime = 0.0f;
  m_fCurrLifeTime = 1000.0f;
  m_bWasUnderWater = true;
  m_pAmount->ResetParam(0.0f);
}


////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

bool CWaterFlow::Preprocess()
{
  bool bQualityCheck = CPostEffectsMgr::CheckPostProcessQuality( eRQ_Medium, eSQ_Medium  );
  if( !bQualityCheck )
    return false;

  if( !CRenderer::CV_r_PostProcessGameFx)
    return false;

  if( m_pAmount->GetParam() > 0.005f)
    return true;

  return false;
}

void CWaterFlow::Reset(bool bOnSpecChange)
{  
  m_pAmount->ResetParam(0.0f);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

bool CWaterVolume::Preprocess()
{
  if( !gRenDev->m_RP.m_eQuality )
    return false;

  if( m_pAmount->GetParam() > 0.005f)
  {
    return true;
  }

  return false;  
}

void CWaterVolume::Reset(bool bOnSpecChange)
{
  m_pAmount->ResetParam(0.0f);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

bool CScreenFrost::Preprocess()
{
  bool bQualityCheck = CPostEffectsMgr::CheckPostProcessQuality( eRQ_Medium, eSQ_Medium );
  if( !bQualityCheck )
    return false;

  if( !CRenderer::CV_r_PostProcessGameFx)
    return false;

  if( m_pAmount->GetParam() > 0.09f)
  {
    return true;
  }

  return false;
}

void CScreenFrost::Reset(bool bOnSpecChange)
{  
  m_pAmount->ResetParam(0.0f);
  m_pCenterAmount->ResetParam(1.0f);
  m_fRandOffset = 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

int CRainDrops::CreateResources()
{
  Release();

  m_ptexMoisture	= CTexture::ForName("EngineAssets/Textures/moisturedroplets.dds", FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);	assert(m_ptexMoisture);
  m_ptexNoise		= CTexture::ForName("EngineAssets/Textures/perlinNoise2d.dds", FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);		assert(m_ptexNoise);

  //create texture for HitEffect accumulation
	m_bFirstFrame = true;

  // Already generated ? No need to proceed
  if( !m_pDropsLst.empty() )
  {
    return 1;
  }

  m_pDropsLst.reserve( m_nMaxDropsCount );
  for(int p=0; p< m_nMaxDropsCount; p++)
  {
    SRainDrop *pDrop = new SRainDrop;
    m_pDropsLst.push_back( pDrop );
  }

	return 1;
}

void CRainDrops::Release()
{ 
  SAFE_RELEASE( m_ptexMoisture );
  SAFE_RELEASE( m_ptexNoise );

  if(m_pDropsLst.empty())
  {
    return;
  }

  SRainDropsItor pItor, pItorEnd = m_pDropsLst.end(); 
  for(pItor=m_pDropsLst.begin(); pItor!=pItorEnd; ++pItor )
  {
    SAFE_DELETE((*pItor));
  } 
  m_pDropsLst.clear(); 
}


void CRainDrops::Reset(bool bOnSpecChange)
{  
  m_bFirstFrame = true;
  m_uCurrentDytex = 0;

  m_pAmount->ResetParam(0.0f);  
  m_pSpawnTimeDistance->ResetParam(0.35f);
  m_pSize->ResetParam(5.0f);
  m_pSizeVar->ResetParam(2.5f);
	m_nAliveDrops = 0;

	m_pMoistureAmount->ResetParam(0.0f);
	m_pMoistureHardness->ResetParam(0.8f);	
	m_pMoistureDropletAmount->ResetParam(3.0f);
	m_pMoistureVariation->ResetParam(2.0f);	
	m_pMoistureSpeed->ResetParam(1.0f);
	m_pMoistureFogAmount->ResetParam(1.0f);
		
	m_vMoistureNoiseOffsets = Vec4(0,0,0,0);
	m_vMoistureDropsOffsets = Vec4(0,0,0,0);
	m_vMoistureRandom		= Vec4(0,0,0,0);
	m_vMoistureDropsFactors	= Vec4(0,0,0,0);

	m_fMoistureStrength = 0.0f;
	m_fMoistureCoverage = 0.0f;
	m_fMoistureFogCoverage = 0.0f;
	m_fMoistureFade		= 1.0f;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

int CNightVision::CreateResources()
{
  SAFE_RELEASE( m_pGradient );
  SAFE_RELEASE( m_pNoise );

  m_pGradient = CTexture::ForName("EngineAssets/Textures/nightvis_grad.dds",  FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);
  m_pNoise = CTexture::ForName("EngineAssets/Textures/vector_noise.dds",  FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);
  //m_pNoise = CTexture::ForName("Textures/Defaults/JumpNoiseHighFrequency_x27y19.dds",  FT_DONT_RELEASE | FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);

	return true;
}

void CNightVision::Release()
{
  SAFE_RELEASE( m_pGradient );
  SAFE_RELEASE( m_pNoise );
}

void CNightVision::Reset(bool bOnSpecChange)
{
	if (!bOnSpecChange)
	{
	  m_pActive->ResetParam(0.0f);
	  m_pAmount->ResetParam(1.0f);  

	  m_bWasActive = false;
	  m_fActiveTime = 0.0f;
	  m_fRandOffset = 0;
	  m_fPrevEyeAdaptionSpeed = 0.25f;
	  m_fPrevEyeAdaptionBase = 100.0f;
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

int CSonarVision::CreateResources()
{
	SAFE_RELEASE( m_pGradient );
	SAFE_RELEASE( m_pNoise );

	m_pGradient = CTexture::ForName("EngineAssets/Shading/SonarVisionGradient.tif",  FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);
	m_pNoise = CTexture::ForName("EngineAssets/Textures/vector_noise.dds",  FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);

	return true;
}

void CSonarVision::Release()
{
	SAFE_RELEASE( m_pGradient );
	SAFE_RELEASE( m_pNoise );
}

void CSonarVision::Reset(bool bOnSpecChange)
{
	m_pActive->ResetParam(0.0f);
	m_pAmount->ResetParam(1.0f);  
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CThermalVision::Release()
{
	SAFE_RELEASE( m_pGradient );
	SAFE_RELEASE( m_pNoise );
}

int CThermalVision::CreateResources()
{
	Release();

	m_pGradient = CTexture::ForName("EngineAssets/Shading/ThermalVisionGradient.tif",  FT_DONT_RESIZE| FT_DONT_STREAM, eTF_Unknown);
	m_pNoise = CTexture::ForName("EngineAssets/Textures/vector_noise.dds",  FT_DONT_RESIZE| FT_DONT_STREAM, eTF_Unknown);

	return true;
}

void CThermalVision::Reset(bool bOnSpecChange)
{
	if (!bOnSpecChange)
	{
		m_pActive->ResetParam(0.0f);
		m_pAmount->ResetParam(1.0f);  
		m_pCamMovNoiseAmount->ResetParam(0.0f);
		m_fBlending = 0.0f;
	}
	m_bInit = true;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CHudSilhouettes::Reset(bool bOnSpecChange)
{
  m_pActive->ResetParam(0.0f);
  m_pAmount->ResetParam(1.0f);  
  m_pType->ResetParam(1);
}

bool CHudSilhouettes::Preprocess()
{
  if( !CRenderer::CV_r_PostProcessGameFx || 
			!CRenderer::CV_r_customvisions || 
			gRenDev->IsCustomRenderModeEnabled(eRMF_THERMALVISION|eRMF_SONARVISION|eRMF_NIGHTVISION) ||
			gRenDev->IsPost3DRendererEnabled())
    return false;





	
  // no need to proceed
  float fType = m_pType->GetParam();
  uint32 nBatchMask = SRendItem::BatchFlags(EFSLIST_GENERAL, gRenDev->m_RP.m_pRLD) | SRendItem::BatchFlags(EFSLIST_TRANSP, gRenDev->m_RP.m_pRLD); 
  if ( (!(nBatchMask & FB_CUSTOM_RENDER)) && fType == 1.0f )
    return false;

  if( m_pAmount->GetParam() > 0.005f )
    return true;

  return false;
}


////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CFlashBang::Release()
{ 
  SAFE_DELETE(m_pGhostImage);
}

void CFlashBang::Reset(bool bOnSpecChange)
{
  SAFE_DELETE( m_pGhostImage );
  m_pActive->ResetParam(0.0f);  
  m_pTime->ResetParam(2.0f);
  m_pDifractionAmount->ResetParam(1.0f);
  m_pBlindAmount->ResetParam(0.5f);
  m_fBlindAmount = 1.0f;
  m_fSpawnTime = 0.0f;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

bool CGammaReference::Preprocess()
{
  if( CRenderer::CV_r_showgammareference )
    return true;

  SAFE_RELEASE( m_pGammaReference );

  return false;
}

void CGammaReference::Reset(bool bOnSpecChange)
{
  m_pActive->ResetParam(0.0f);  
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CPostAA::Reset(bool bOnSpecChange)
{
	m_bInit = true;
	m_nScopeZoomTransition = 0;
	m_pScopeZoom->ResetParam(0.0f);
}

int CPostAA::CreateResources()
{
	SAFE_RELEASE(m_pAreaSMAA);
	SAFE_RELEASE(m_pSearchSMAA);

	m_pAreaSMAA = CTexture::ForName("EngineAssets/ScreenSpace/AreaTex.dds",  FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);
	m_pSearchSMAA = CTexture::ForName("EngineAssets/ScreenSpace/SearchTex.dds",  FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);

	return 1;
}

void CPostAA::Release()
{
	SAFE_RELEASE(m_pAreaSMAA);
	SAFE_RELEASE(m_pSearchSMAA);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CSoftAlphaTest::Reset(bool bOnSpecChange)
{
}

bool CSoftAlphaTest::Preprocess()
{
	uint32 nBatchMask = SRendItem::BatchFlags(EFSLIST_GENERAL, gRenDev->m_RP.m_pRLD);
	return CRenderer::CV_r_SoftAlphaTest != 0 && (nBatchMask & FB_SOFTALPHATEST);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CPostStereo::Reset(bool bOnSpecChange)
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

bool CImageGhosting::Preprocess()
{	
	CTexture *pPrevFrame = CTexture::s_ptexPrevFrameScaled;
	if( !pPrevFrame )
	{
		m_bInit = true;
		return false;
	}

	if( m_pAmount->GetParam() > 0.09f)
		return true;

	m_bInit = true;

	return false;
}

void CImageGhosting::Reset(bool bOnSpecChange)
{
	m_bInit = true;
	m_pAmount->ResetParam(0.0f);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

int CFilterKillCamera::Initialize()
{
	m_techName = "KillCameraFilter";
	m_paramName = "psParams";
	return 1;
}

bool CFilterKillCamera::Preprocess()
{
	if(!CRenderer::CV_r_PostProcessFilters)
		return false;

	if( m_pActive->GetParam() > 0.0f )
	{
		return true;
	}

	m_blindTimer = 0.0f;

	return false;
}

void CFilterKillCamera::Reset(bool bOnSpecChange)
{
	m_pActive->ResetParam(0.0f);
	m_pGrainStrength->ResetParam(0.0f);
	m_pChromaShift->ResetParamVec4(Vec4(1.0f, 0.5f, 0.1f, 1.0f)); // xyz = offset, w = strength
	m_pVignette->ResetParamVec4(Vec4(1.0f, 1.0f, 0.5f, 1.4f)); // xy = screen scale, z = radius, w = blind noise vignette scale
	m_pColorScale->ResetParamVec4(Vec4(1.0f, 1.0f, 1.0f, 1.0f));
	m_pBlindness->ResetParamVec4(Vec4(0.5f, 0.5f, 1.0f, 0.7f)); // x = blind duration, y = blind fade out duration, z = blindness grey scale, w =  blind noise min scale
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

int CNanoGlass::CreateResources()
{
  m_pHexOutline = CTexture::ForName("EngineAssets/Textures/hex.dds",  FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);
  m_pHexNormal = CTexture::ForName("EngineAssets/Textures/hex_ddn.dds",  FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);
  m_pNoise = CTexture::ForName("EngineAssets/Textures/perlinNoise_sum_small.dds", FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);
	return 1;
}

void CNanoGlass::Release()
{
	SAFE_RELEASE( m_pHexOutline );
	SAFE_RELEASE( m_pHexNormal );
	SAFE_RELEASE( m_pNoise );
}

bool CNanoGlass::Preprocess()
{
	if(!CRenderer::CV_r_PostProcessFilters)
		return false;

	CEffectParam* pHUDHitEffectAreaVisibility = PostEffectMgr()->GetByName("HUDHitEffect_AreaVisibility");
	if(pHUDHitEffectAreaVisibility)
	{
		pHUDHitEffectAreaVisibility->SetParam(m_pActive->GetParam() > 0.0f ? 0.0f : 1.0f, true);
	}

	if( m_pActive->GetParam() > 0.0f )
	{
		return true;
	}

	m_noiseTime = 0.0f;
	m_time = 0.0f;
	return false;
}

void CNanoGlass::Reset(bool bOnSpecChange)
{
	// The post effect manager now gets reset at the start of the game - seems to be because the shader quality
	// gets changed between menus and game.
	// This reset gets called after this post effect is turned on, so cannot use this as a reliable reset, 
	// will have to rely on game code to control this effect and reset it. All these values do get set in the
	// constructor. This post effect is recreated at the start of each session, so the constructor gets called then
}

void CNanoGlass::AddRE( const CRendElementBase *pRE, const SShaderItem *pShaderItem, CRenderObject *pObj)
{
	// Main thread
	const uint32 nThreadID = gRenDev->m_RP.m_nFillThreadID;		
	// Only add valid render elements
	if( pRE && pObj )         
	{
		m_pRenderData[nThreadID].pRenderElement = pRE;
		m_pRenderData[nThreadID].pRenderObject = pObj;
	}
}
//////////////////////////////////////////////////////////////////////////

const	CCryNameTSCRC	CHUDHitEffect::s_tnAttenuationPass("HUDHitEffectAttenuation");
const	CCryNameTSCRC	CHUDHitEffect::s_tnHitAccumulationPass("HUDHitEffectHitAccumulation");
const	CCryNameTSCRC	CHUDHitEffect::s_tnFlashAccumulationPass("HUDHitEffectFlashAccumulation");
const	CCryNameTSCRC	CHUDHitEffect::s_tnHealthDisplayPass("HUDHitEffectHealthDisplay");

const	CCryNameR		CHUDHitEffect::s_pnAttenuationParams("vHUDHitEffect_AttenuationParams");
const	CCryNameR		CHUDHitEffect::s_pnNoiseParams("vHUDHitEffect_NoiseParams");

const	CCryNameR		CHUDHitEffect::s_pnHitParams("vHUDHitEffect_Params");

const	CCryNameR		CHUDHitEffect::s_pnDisplayParams("vHUDHitEffect_DisplayParams");
const	CCryNameR		CHUDHitEffect::s_pnHealthParams("vHUDHitEffect_HealthParams");

CHUDHitEffect::SHitImpact::SHitImpact(float fStrength, float fImpactSpeed, const Vec4& vHitDirection):
	_bStarted(false),
	_fFlashDrawTime(3.0f),
	_bFlashPosInited(false),
	_fCumulTime(0.0f),
	_fStrength(fStrength),
	_fImpactSpeed(fImpactSpeed),		
	_vCurrentPosition(0.0f, 0.0f, 0.0f, 1.0f),
	_vFlashPosition(0.0f, 0.0f, 0.0f, 1.0f),
	_vHitDirection(vHitDirection)

{
	if(_fStrength > 0.0f && _fImpactSpeed > 0.0f)
		_bStarted = true;
}


CHUDHitEffect::CHUDHitEffect():		
	m_b1stFrame(true),
	m_fNanoLevel(1.0f),			m_fNanoLevelT(1.0f),
	m_fVeinsLevel(1.0f),		m_fVeinsLevelT(1.0f),
	m_fColorLevel(1.0f),		m_fColorLevelT(1.0f),
	m_fTilingFactor(50.0f),		m_fTilingFactorT(50.0f),
	m_fFlickerFrequency(1.0f),	m_fFlickerFrequencyT(1.0f),
	m_fAreaVisibility(1.0f),	m_fAreaVisibilityT(1.0f),
	m_ptexPerlinNoise(0),
	m_ptexImpactRound(0),
	m_ptexNanoPatternLine(0),	
	m_ptexVeinsBlood(0),
	m_ptexHealthGradient(0),
	m_ptexVignetteAreas(0),
	m_ptexBlurMask_ddn(0)
{
	m_nID = ePFX_HUDHitEffect;
	m_nRenderFlags = PSP_REQUIRES_UPDATE;

	AddParamBool(	"HUDHitEffect_Active",	m_pActive, 0 );
	AddParamFloat(	"HUDHitEffect_Amount",	m_pAmount, 0.0f );

	AddParamFloat(	"HUDHitEffect_DisplayTime",	m_pDisplayTime,	3.0f);
	AddParamFloat(	"HUDHitEffect_AnimSpeed",	m_pAnimSpeed, 0.01f);

	AddParamFloatNoTransition(	"HUDHitEffect_HealthLevel",	m_pHealthLevel, 1.0f);
	AddParamFloatNoTransition(	"HUDHitEffect_HealthNanoOffset", m_pHealthNanoOffset, 0.9f);
	AddParamFloatNoTransition(	"HUDHitEffect_HealthVeinsOffset", m_pHealthVeinsOffset, 0.6f);
	AddParamFloatNoTransition(	"HUDHitEffect_ColorFadeOffset", m_pColorFadeOffset, 0.4f);
	AddParamFloatNoTransition(	"HUDHitEffect_NanoPatternTiling", m_pNanoPatternTiling, 50.0f);

	AddParamVec4NoTransition("HUDHitEffect_HitDirection", m_pHitDirection, Vec4(0.0f, 0.0f, 0.0f, 0.0f));		  
	AddParamFloatNoTransition("HUDHitEffect_HitStrength", m_pHitStrength, 0.0f);
	AddParamFloatNoTransition("HUDHitEffect_HitSpeed", m_pHitSpeed, 0.0f);
	AddParamFloat("HUDHitEffect_HitAttenuation", m_pHitAttenuation, 0.05f);
	AddParamFloat("HUDHitEffect_HitAttenuationBlur", m_pHitAttenuationBlur, 0.01f);
	AddParamFloatNoTransition("HUDHitEffect_HitAreaVisibility", m_pHitAreaVisibility, 1.0f);

	AddParamFloat(	"HUDHitEffect_CriticalSaturation",	m_pCriticalSaturation,	0.4f );	
	AddParamFloat(	"HUDHitEffect_CriticalBrightness",	m_pCriticalBrightness,	1.0f );
	AddParamFloat(	"HUDHitEffect_CriticalContrast",	m_pCriticalContrast,	1.0f );

	AddParamFloat(	"HUDHitEffect_NoiseAmount",	m_pNoiseAmount,	1.0f);

	AddParamFloat(	"HUDHitEffect_ScreenBorderLeft", m_pScreenBorderLeft, 0.1f);
	AddParamFloat(	"HUDHitEffect_ScreenBorderTop", m_pScreenBorderTop, 0.15f);
	AddParamFloat(	"HUDHitEffect_ScreenBorderRight", m_pScreenBorderRight, 0.1f);
	AddParamFloat(	"HUDHitEffect_ScreenBorderBottom", m_pScreenBorderBottom, 0.15f);
	
	m_uCurrentDytex = 0;

	m_iActiveImpacts = 0;
	m_iCurrent1stImpact = 0;
}

CHUDHitEffect::~CHUDHitEffect()
{
	//Release();
	//ReleaseDynTextures();
}

int		CHUDHitEffect::CreateResources()
{
	return 1;
	
	//Release();
	//ReleaseDynTextures();	
	////load textures
	//m_ptexPerlinNoise		= CTexture::ForName("EngineAssets/Textures/perlinnoise_sum.dds", FT_DONT_RELEASE | FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);		assert(m_ptexPerlinNoise);
	//m_ptexImpactRound		= CTexture::ForName("EngineAssets/Textures/hiteffect_round.dds", FT_DONT_RELEASE | FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);		assert(m_ptexImpactRound);

	//m_ptexNanoPatternLine	= CTexture::ForName("EngineAssets/Textures/hex_line.dds", FT_DONT_RELEASE | FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);				assert(m_ptexNanoPatternLine);
	//m_ptexVeinsBlood		= CTexture::ForName("EngineAssets/Textures/hiteffect_veinsblood.dds", FT_DONT_RELEASE | FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);	assert(m_ptexVeinsBlood);

	//m_ptexHealthGradient	= CTexture::ForName("EngineAssets/Textures/hiteffect_healthgradient.dds", FT_DONT_RELEASE | FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);	assert(m_ptexHealthGradient);
	//m_ptexVignetteAreas		= CTexture::ForName("EngineAssets/Textures/hiteffect_areas.dds", FT_DONT_RELEASE | FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);		assert(m_ptexVignetteAreas);
	//m_ptexBlurMask_ddn		= CTexture::ForName("EngineAssets/Textures/hiteffect_blurmask_ddn.dds", FT_DONT_RELEASE | FT_DONT_RESIZE | FT_DONT_STREAM, eTF_Unknown);assert(m_ptexBlurMask_ddn);

	////create texture for HitEffect accumulation
	//if(!CreateDynTextures())
	//	return 0;

	return 1;
}

void	CHUDHitEffect::Release()
{
	////release static textures	
	//SAFE_RELEASE( m_ptexPerlinNoise );
	//SAFE_RELEASE( m_ptexImpactRound );
	//SAFE_RELEASE( m_ptexNanoPatternLine );
	//SAFE_RELEASE( m_ptexVeinsBlood );
	//SAFE_RELEASE( m_ptexHealthGradient );
	//SAFE_RELEASE( m_ptexVignetteAreas );
	//SAFE_RELEASE( m_ptexBlurMask_ddn );
}

void	CHUDHitEffect::Reset(bool bOnSpecChange)
{
	m_pActive->ResetParam(0.0f);
	m_pAmount->ResetParam(0.0f);

	for(int i = 0; i < sm_HitImpactCount; ++i)
	{
		m_aHitImpacts[i] = SHitImpact();	//no new, just reset
	}

	m_pHealthLevel->ResetParam(1.0f);
	m_pHealthNanoOffset->ResetParam(0.9f);
	m_pHealthVeinsOffset->ResetParam(0.6f);
	m_pColorFadeOffset->ResetParam(0.4f);
	m_pNanoPatternTiling->ResetParam(50.0f);

	m_pHitDirection->ResetParamVec4(Vec4(0.0f, 0.0f, 0.0f, 0.0f));	
	m_pHitStrength->ResetParam(0.0f);
	m_pHitSpeed->ResetParam(0.0f);
	m_pHitAttenuation->ResetParam(0.05f);
	m_pHitAttenuationBlur->ResetParam(0.01f);
	m_pHitAreaVisibility->ResetParam(1.0f);

	m_pCriticalSaturation->ResetParam(0.4f);
	m_pCriticalBrightness->ResetParam(1.0f);
	m_pCriticalContrast->ResetParam(1.0f);
	
	m_pDisplayTime->ResetParam(3.0f);	
	m_pAnimSpeed->ResetParam(0.01f);
	
	m_pNoiseAmount->ResetParam(1.0f);

	m_pScreenBorderLeft->ResetParam(0.1f);
	m_pScreenBorderTop->ResetParam(0.15f);
	m_pScreenBorderRight->ResetParam(0.1f);
	m_pScreenBorderBottom->ResetParam(0.15f);

	m_b1stFrame = true;

	m_fNanoLevelT			= 1.0f;
	m_fVeinsLevelT			= 1.0f;
	m_fColorLevelT			= 1.0f;
	m_fAreaVisibilityT		= 1.0f;
	m_fFlickerFrequency		= 1.0f;
	m_fFlickerFrequencyT	= 1.0f;

	m_iActiveImpacts = 0;
	m_iCurrent1stImpact = 0;
}



bool	CHUDHitEffect::Preprocess()
{
	if(!CRenderer::CV_r_PostProcessFilters || !CRenderer::CV_r_HUDHitEffect)
		return false;

	//leave this like it is, else flownode does not work
	bool bActive( m_pActive->GetParam() > EPSILON || m_pAmount->GetParam() > EPSILON );
	
	//something already spawned
	bool bStartedCumul = false;
	for(int i = 0; i < sm_HitImpactCount; ++i)
	{
		bStartedCumul = bStartedCumul || m_aHitImpacts[i]._bStarted;
	}
	//something to spawn
	bool bSomethingToSpawn(	m_pHitStrength->GetParam() > 0.0f	||	m_pHitSpeed->GetParam() > 0.0f);

	//fading health display
	bool bLevelsFading(m_fNanoLevelT < 1.0f || m_fVeinsLevelT < 1.0f || m_fColorLevelT < 1.0f);	

	if(bActive && (bStartedCumul || bSomethingToSpawn || bLevelsFading))
		return true;

	return false;
}


void	CHUDHitEffect::AddRE( const CRendElementBase* pRE, const SShaderItem* pShaderItem, CRenderObject* pObj )
{
	// Main thread
	const uint32 nThreadID = gRenDev->m_RP.m_nFillThreadID;		
	// Only add valid render elements
	if( pRE && pObj )         
	{
		m_pRenderData[nThreadID].pRenderElement = pRE;
		m_pRenderData[nThreadID].pRenderObject = pObj;
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CScreenBlood::Reset(bool bOnSpecChange)
{
	m_pAmount->ResetParam(0.0f);
}

bool CScreenBlood::Preprocess()
{
	return ( CRenderer::CV_r_PostProcessGameFx && m_pAmount->GetParam() > 0.005f );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

void CScreenGlassShards::Reset(bool bOnSpecChange)
{
	m_pAmount->ResetParam(0.0f);
}

bool CScreenGlassShards::Preprocess()
{
	return ( CRenderer::CV_r_PostProcessGameFx && m_pAmount->GetParam() > 0.005f );
}

//////////////////////////////////////////////////////////////////////////

void CPost3DRenderer::Reset(bool bOnSpecChange)
{
	// Let game code fully control its active status, otherwise in some situations
	// the post effect system will get reset between menus and game and thus this
	// will get turned off when undesired
}

//////////////////////////////////////////////////////////////////////////
const Vec4	CScreenFog::m_vDefaultColor(0.5f, 0.5f, 0.5f, 0.0f);

CScreenFog::CScreenFog()
{
	m_nRenderFlags = 0;
	m_nID = ePFX_eScreenFog;		
	AddParamFloat("ScreenFog_Amount", m_pAmount, 0.0f);	
	AddParamVec4("ScreenFog_Color", m_pFogColor, m_vDefaultColor);
}

CScreenFog::~CScreenFog()
{
	Release();
}

bool CScreenFog::Preprocess()
{
	return ( CRenderer::CV_r_PostProcessGameFx && m_pAmount->GetParam() > 0.0001f );
}

void CScreenFog::Reset(bool bOnSpecChange)
{
	m_pAmount->ResetParam(0.0f);
	m_pFogColor->ResetParamVec4(m_vDefaultColor);
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
